home *** CD-ROM | disk | FTP | other *** search
/ Games of Daze / Infomagic - Games of Daze (Summer 1995) (Disc 1 of 2).iso / djgpp / src / binutils.252 / ld / ldexp.c < prev    next >
Encoding:
C/C++ Source or Header  |  1994-09-27  |  20.8 KB  |  878 lines

  1. /* This module handles expression trees.
  2. Copyright (C) 1991, 1993 Free Software Foundation, Inc.
  3. Written by Steve Chamberlain of Cygnus Support (sac@cygnus.com).
  4.  
  5. This file is part of GLD, the Gnu Linker.
  6.  
  7. GLD is free software; you can redistribute it and/or modify
  8. it under the terms of the GNU General Public License as published by
  9. the Free Software Foundation; either version 2, or (at your option)
  10. any later version.
  11.  
  12. GLD is distributed in the hope that it will be useful,
  13. but WITHOUT ANY WARRANTY; without even the implied warranty of
  14. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  15. GNU General Public License for more details.
  16.  
  17. You should have received a copy of the GNU General Public License
  18. along with GLD; see the file COPYING.  If not, write to
  19. the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.  */
  20.  
  21. /*
  22. This module is in charge of working out the contents of expressions.
  23.  
  24. It has to keep track of the relative/absness of a symbol etc. This is
  25. done by keeping all values in a struct (an etree_value_type) which
  26. contains a value, a section to which it is relative and a valid bit.
  27.  
  28. */
  29.  
  30.  
  31. #include "bfd.h"
  32. #include "sysdep.h"
  33. #include "bfdlink.h"
  34.  
  35. #include "ld.h"
  36. #include "ldmain.h"
  37. #include "ldmisc.h"
  38. #include "ldexp.h"
  39. #include "ldgram.h"
  40. #include "ldlang.h"
  41.  
  42. static void exp_print_token PARAMS ((token_code_type code));
  43. static void make_abs PARAMS ((etree_value_type *ptr));
  44. static etree_value_type new_abs PARAMS ((bfd_vma value));
  45. static void check PARAMS ((lang_output_section_statement_type *os,
  46.                const char *name, const char *op));
  47. static etree_value_type new_rel
  48.   PARAMS ((bfd_vma value, lang_output_section_statement_type *section));
  49. static etree_value_type new_rel_from_section
  50.   PARAMS ((bfd_vma value, lang_output_section_statement_type *section));
  51. static etree_value_type fold_binary
  52.   PARAMS ((etree_type *tree,
  53.        lang_output_section_statement_type *current_section,
  54.        lang_phase_type allocation_done,
  55.        bfd_vma dot, bfd_vma *dotp));
  56. static etree_value_type fold_name
  57.   PARAMS ((etree_type *tree,
  58.        lang_output_section_statement_type *current_section,
  59.        lang_phase_type allocation_done,
  60.        bfd_vma dot));
  61. static etree_value_type exp_fold_tree_no_dot
  62.   PARAMS ((etree_type *tree,
  63.        lang_output_section_statement_type *current_section,
  64.        lang_phase_type allocation_done));
  65.  
  66. static void
  67. exp_print_token (code)
  68.      token_code_type code;
  69. {
  70.   static CONST struct
  71.     {
  72.       token_code_type code;
  73.       char *name;
  74.     } table[] =
  75.       {
  76.     { INT,    "int" },
  77.     { REL, "relocateable" },
  78.     { NAME,"NAME" },
  79.     { PLUSEQ,"+=" },
  80.     { MINUSEQ,"-=" },
  81.     { MULTEQ,"*=" },
  82.     { DIVEQ,"/=" },
  83.     { LSHIFTEQ,"<<=" },
  84.     { RSHIFTEQ,">>=" },
  85.     { ANDEQ,"&=" },
  86.     { OREQ,"|=" },
  87.     { OROR,"||" },
  88.     { ANDAND,"&&" },
  89.     { EQ,"==" },
  90.     { NE,"!=" },
  91.     { LE,"<=" },
  92.     { GE,">=" },
  93.     { LSHIFT,"<<" },
  94.     { RSHIFT,">>=" },
  95.     { ALIGN_K,"ALIGN" },
  96.     { BLOCK,"BLOCK" },
  97.     { SECTIONS,"SECTIONS" },
  98.     { SIZEOF_HEADERS,"SIZEOF_HEADERS" },
  99.     { NEXT,"NEXT" },
  100.     { SIZEOF,"SIZEOF" },
  101.     { ADDR,"ADDR" },
  102.     { MEMORY,"MEMORY" },
  103.     { DEFINED,"DEFINED" },
  104.     { TARGET_K,"TARGET" },
  105.     { SEARCH_DIR,"SEARCH_DIR" },
  106.     { MAP,"MAP" },
  107.     { QUAD,"QUAD" },
  108.     { LONG,"LONG" },
  109.     { SHORT,"SHORT" },
  110.     { BYTE,"BYTE" },
  111.     { ENTRY,"ENTRY" },
  112.     { 0,(char *)NULL }
  113.       };
  114.   unsigned int idx;
  115.  
  116.   for (idx = 0; table[idx].name != (char*)NULL; idx++) {
  117.     if (table[idx].code == code) {
  118.       fprintf(config.map_file, "%s", table[idx].name);
  119.       return;
  120.     }
  121.   }
  122.   /* Not in table, just print it alone */
  123.   fprintf(config.map_file, "%c",code);
  124. }
  125.  
  126. static void 
  127. make_abs (ptr)
  128.      etree_value_type *ptr;
  129. {
  130.     asection *s = ptr->section->bfd_section;
  131.     ptr->value += s->vma;
  132.     ptr->section = abs_output_section;
  133. }
  134.  
  135. static etree_value_type
  136. new_abs (value)
  137.      bfd_vma value;
  138. {
  139.   etree_value_type new;
  140.   new.valid = true;
  141.   new.section = abs_output_section;
  142.   new.value = value;
  143.   return new;
  144. }
  145.  
  146. static void 
  147. check (os, name, op)
  148.      lang_output_section_statement_type *os;
  149.      CONST char *name;
  150.      CONST char *op;
  151. {
  152.   if (os == (lang_output_section_statement_type *)NULL) {
  153.     einfo("%F%P: %s uses undefined section %s\n", op, name);
  154.   }
  155.   if (os->processed == false) {
  156.     einfo("%F%P: %s forward reference of section %s\n",op, name);
  157.   }
  158. }
  159.  
  160. etree_type *
  161. exp_intop (value)
  162.      bfd_vma value;
  163. {
  164.   etree_type *new = (etree_type *)stat_alloc((bfd_size_type)(sizeof(new->value)));
  165.   new->type.node_code = INT;
  166.   new->value.value = value;
  167.   new->type.node_class = etree_value;
  168.   return new;
  169.  
  170. }
  171.  
  172. /* Build an expression representing an unnamed relocateable value.  */
  173.  
  174. etree_type *
  175. exp_relop (section, value)
  176.      asection *section;
  177.      bfd_vma value;
  178. {
  179.   etree_type *new = (etree_type *) stat_alloc (sizeof (new->rel));
  180.   new->type.node_code = REL;
  181.   new->type.node_class = etree_rel;
  182.   new->rel.section = section;
  183.   new->rel.value = value;
  184.   return new;
  185. }
  186.  
  187. static etree_value_type
  188. new_rel (value, section)
  189.      bfd_vma value;
  190.      lang_output_section_statement_type *section;
  191. {
  192.   etree_value_type new;
  193.   new.valid = true;
  194.   new.value = value;
  195.   new.section = section;
  196.   return new;
  197. }
  198.  
  199. static etree_value_type
  200. new_rel_from_section (value, section)
  201.      bfd_vma value;
  202.      lang_output_section_statement_type *section;
  203. {
  204.   etree_value_type new;
  205.   new.valid = true;
  206.   new.value = value;
  207.   new.section = section;
  208.  
  209.     new.value -= section->bfd_section->vma;
  210.  
  211.   return new;
  212. }
  213.  
  214. static etree_value_type 
  215. fold_binary (tree, current_section, allocation_done, dot, dotp)
  216.      etree_type *tree;
  217.      lang_output_section_statement_type *current_section;
  218.      lang_phase_type  allocation_done;
  219.      bfd_vma dot;
  220.      bfd_vma *dotp;
  221. {
  222.   etree_value_type result;
  223.  
  224.   result =  exp_fold_tree(tree->binary.lhs,  current_section,
  225.               allocation_done, dot, dotp);
  226.   if (result.valid) {
  227.     etree_value_type other;
  228.     other = exp_fold_tree(tree->binary.rhs,
  229.               current_section,
  230.               allocation_done, dot,dotp) ;
  231.     if (other.valid) {
  232.     /* If values are from different sections, or this is an */
  233.     /* absolute expression, make both source args absolute */
  234.       if (result.section !=  other.section ||
  235.       current_section == abs_output_section) 
  236.       {
  237.     make_abs(&result);
  238.     make_abs(&other);
  239.       }
  240.       
  241.       switch (tree->type.node_code) 
  242.     {
  243.     case '%':
  244.       /* Mod,  both absolule*/
  245.  
  246.       if (other.value == 0) {
  247.         einfo("%F%S %% by zero\n");
  248.       }
  249.       result.value = (int)result.value % (int)other.value;
  250.       break;
  251.     case '/':
  252.       if (other.value == 0) {
  253.         einfo("%F%S / by zero\n");
  254.       }
  255.       result.value = (int)result.value / (int) other.value;
  256.       break;
  257. #define BOP(x,y) case x : result.value = result.value y other.value;break;
  258.       BOP('+',+);
  259.       BOP('*',*);
  260.       BOP('-',-);
  261.       BOP(LSHIFT,<<);
  262.       BOP(RSHIFT,>>);
  263.       BOP(EQ,==);
  264.       BOP(NE,!=);
  265.       BOP('<',<);
  266.       BOP('>',>);
  267.       BOP(LE,<=);
  268.       BOP(GE,>=);
  269.       BOP('&',&);
  270.       BOP('^',^);
  271.       BOP('|',|);
  272.       BOP(ANDAND,&&);
  273.       BOP(OROR,||);
  274.     default:
  275.       FAIL();
  276.     }
  277.     }
  278.     else {
  279.       result.valid = false;
  280.     }
  281.   }
  282.   return result;
  283. }
  284. etree_value_type 
  285. invalid ()
  286. {
  287.   etree_value_type new;
  288.   new.valid = false;
  289.   return new;
  290. }
  291.  
  292. static etree_value_type 
  293. fold_name (tree, current_section, allocation_done, dot)
  294.      etree_type *tree;
  295.      lang_output_section_statement_type *current_section;
  296.      lang_phase_type  allocation_done;
  297.      bfd_vma dot;
  298. {
  299.   etree_value_type result;
  300.   switch (tree->type.node_code) 
  301.       {
  302.       case SIZEOF_HEADERS:
  303.     if (allocation_done != lang_first_phase_enum) 
  304.       {
  305.         result = new_abs ((bfd_vma)
  306.                   bfd_sizeof_headers (output_bfd,
  307.                           link_info.relocateable));
  308.       }
  309.     else
  310.       {
  311.         result.valid = false;
  312.       }
  313.     break;
  314.       case DEFINED:
  315.     if (allocation_done == lang_first_phase_enum)
  316.       result.valid = false;
  317.     else
  318.       {
  319.         struct bfd_link_hash_entry *h;
  320.  
  321.         h = bfd_link_hash_lookup (link_info.hash, tree->name.name,
  322.                       false, false, true);
  323.         result.value = (h != (struct bfd_link_hash_entry *) NULL
  324.                 && (h->type == bfd_link_hash_defined
  325.                 || h->type == bfd_link_hash_common));
  326.         result.section = 0;
  327.         result.valid = true;
  328.       }
  329.     break;
  330.       case NAME:
  331.     result.valid = false;
  332.     if (tree->name.name[0] == '.' && tree->name.name[1] == 0)
  333.       {
  334.         if (allocation_done != lang_first_phase_enum)
  335.           result = new_rel_from_section(dot, current_section);
  336.         else
  337.           result = invalid();
  338.       }
  339.     else if (allocation_done == lang_final_phase_enum)
  340.       {
  341.         struct bfd_link_hash_entry *h;
  342.  
  343.         h = bfd_link_hash_lookup (link_info.hash, tree->name.name,
  344.                       false, false, true);
  345.         if (h != (struct bfd_link_hash_entry *) NULL
  346.         && h->type == bfd_link_hash_defined)
  347.           {
  348.         lang_output_section_statement_type *os;
  349.         
  350.         os = (lang_output_section_statement_lookup
  351.               (h->u.def.section->output_section->name));
  352.  
  353.         /* FIXME: Is this correct if this section is being
  354.            linked with -R?  */
  355.         result = new_rel ((h->u.def.value
  356.                    + h->u.def.section->output_offset),
  357.                   os);
  358.           }
  359.         if (result.valid == false)
  360.           einfo("%F%S: undefined symbol `%s' referenced in expression\n",
  361.             tree->name.name);
  362.       }
  363.     break;
  364.  
  365.       case ADDR:
  366.  
  367.     if (allocation_done != lang_first_phase_enum) {
  368.       lang_output_section_statement_type *os =
  369.         lang_output_section_find(tree->name.name);
  370.       check(os,tree->name.name,"ADDR");
  371.       result =    new_rel((bfd_vma)0,  os);
  372.     }
  373.     else {
  374.       result = invalid();
  375.     }
  376.     break;
  377.       case SIZEOF:
  378.     if(allocation_done != lang_first_phase_enum) {
  379.       lang_output_section_statement_type *os = 
  380.         lang_output_section_find(tree->name.name);
  381.       check(os,tree->name.name,"SIZEOF");
  382.       result = new_abs((bfd_vma)(os->bfd_section->_raw_size));
  383.     }
  384.     else {
  385.       result = invalid();
  386.     }
  387.     break;
  388.  
  389.       default:
  390.     FAIL();
  391.     break;
  392.       }
  393.  
  394.   return result;
  395. }
  396. etree_value_type 
  397. exp_fold_tree (tree, current_section, allocation_done, dot, dotp)
  398.      etree_type *tree;
  399.      lang_output_section_statement_type *current_section;
  400.      lang_phase_type  allocation_done;
  401.      bfd_vma dot;
  402.      bfd_vma *dotp;
  403. {
  404.   etree_value_type result;
  405.  
  406.   if (tree == (etree_type *)NULL) {
  407.     result.valid = false;
  408.   }
  409.   else {
  410.     switch (tree->type.node_class) 
  411.     {
  412.      case etree_value:
  413.       result = new_rel(tree->value.value, current_section);
  414.       break;
  415.     case etree_rel:
  416.       if (allocation_done != lang_final_phase_enum)
  417.     result.valid = false;
  418.       else
  419.     result = new_rel ((tree->rel.value
  420.                + tree->rel.section->output_section->vma
  421.                + tree->rel.section->output_offset),
  422.               current_section);
  423.       break;
  424.      case etree_unary:
  425.       result = exp_fold_tree(tree->unary.child,
  426.                  current_section,
  427.                  allocation_done, dot, dotp);
  428.       if (result.valid == true)
  429.       {
  430.     switch(tree->type.node_code) 
  431.     {
  432.      case ALIGN_K:
  433.       if (allocation_done != lang_first_phase_enum) {
  434.         result = new_rel_from_section(ALIGN_N(dot,
  435.                         result.value) ,
  436.                       current_section);
  437.  
  438.       }
  439.       else {
  440.         result.valid = false;
  441.       }
  442.       break;
  443.      case ABSOLUTE:
  444.       if (allocation_done != lang_first_phase_enum) 
  445.       {
  446.         if (current_section 
  447.         == (lang_output_section_statement_type*)NULL) 
  448.         {
  449.           /* Outside a section, so it's all ok */
  450.  
  451.         }
  452.         else {
  453.           /* Inside a section, subtract the base of the section,
  454.          so when it's added again (in an assignment), everything comes out fine
  455.          */
  456.           result.section = abs_output_section;
  457.           result.value -= current_section->bfd_section->vma;
  458.           result.valid = true;
  459.         }
  460.       }
  461.       else 
  462.       {
  463.         result.valid = false;
  464.       }
  465.  
  466.       break;
  467.      case '~':
  468.       make_abs(&result);
  469.       result.value = ~result.value;
  470.       break;
  471.      case '!':
  472.       make_abs(&result);
  473.       result.value = !result.value;
  474.       break;
  475.      case '-':
  476.       make_abs(&result);
  477.       result.value = -result.value;
  478.       break;
  479.      case NEXT:
  480.       if (allocation_done ==lang_allocating_phase_enum) {
  481.         make_abs(&result);
  482.         result.value = ALIGN_N(dot, result.value);
  483.       }
  484.       else {
  485.         /* Return next place aligned to value */
  486.         result.valid = false;
  487.       }
  488.       break;
  489.      default:
  490.       FAIL();
  491.     }
  492.       }
  493.  
  494.       break;
  495.      case etree_trinary:
  496.  
  497.       result = exp_fold_tree(tree->trinary.cond,
  498.                  current_section,
  499.                  allocation_done, dot, dotp);
  500.       if (result.valid) {
  501.     result = exp_fold_tree(result.value ?
  502.                    tree->trinary.lhs:tree->trinary.rhs,
  503.                    current_section,
  504.                    allocation_done, dot, dotp);
  505.       }
  506.  
  507.       break;
  508.      case etree_binary:
  509.       result = fold_binary(tree, current_section, allocation_done,
  510.                dot, dotp);
  511.       break;
  512.      case etree_assign:
  513.      case etree_provide:
  514.       if (tree->assign.dst[0] == '.' && tree->assign.dst[1] == 0) {
  515.     /* Assignment to dot can only be done during allocation */
  516.     if (tree->type.node_class == etree_provide)
  517.       einfo ("%F%S can not PROVIDE assignment to location counter\n");
  518.     if (allocation_done == lang_allocating_phase_enum) {
  519.       result = exp_fold_tree(tree->assign.src,
  520.                  current_section,
  521.                  lang_allocating_phase_enum, dot, dotp);
  522.       if (result.valid == false) {
  523.         einfo("%F%S invalid assignment to location counter\n");
  524.       }
  525.       else {
  526.         if (current_section ==
  527.         (lang_output_section_statement_type  *)NULL) {
  528.           einfo("%F%S assignment to location counter invalid outside of SECTION\n");
  529.         }
  530.         else {
  531.           bfd_vma nextdot =result.value +
  532.            current_section->bfd_section->vma;
  533.           if (nextdot < dot) {
  534.         einfo("%F%S cannot move location counter backwards (from %V to %V)\n", dot, nextdot);
  535.           }
  536.           else {
  537.         *dotp = nextdot; 
  538.           }
  539.         }
  540.       }
  541.     }
  542.       }
  543.       else
  544.     {
  545.       result = exp_fold_tree (tree->assign.src,
  546.                   current_section, allocation_done,
  547.                   dot, dotp);
  548.       if (result.valid)
  549.         {
  550.           struct bfd_link_hash_entry *h;
  551.  
  552.           h = bfd_link_hash_lookup (link_info.hash, tree->assign.dst,
  553.                     (tree->type.node_class == etree_assign
  554.                      ? true : false),
  555.                     false, false);
  556.           if (h == (struct bfd_link_hash_entry *) NULL)
  557.         {
  558.           if (tree->type.node_class == etree_assign)
  559.             einfo ("%P%F:%s: hash creation failed\n",
  560.                tree->assign.dst);
  561.         }
  562.           else if (tree->type.node_class == etree_provide
  563.                && h->type != bfd_link_hash_undefined
  564.                && h->type != bfd_link_hash_common)
  565.         {
  566.           /* Do nothing.  The symbol was defined by some
  567.                      object.  */
  568.         }
  569.           else
  570.         {
  571.           /* FIXME: Should we worry if the symbol is already
  572.              defined?  */
  573.           h->type = bfd_link_hash_defined;
  574.           h->u.def.value = result.value;
  575.           h->u.def.section = result.section->bfd_section;
  576.         }
  577.         }
  578.     }  
  579.       break;
  580.      case etree_name:
  581.       result = fold_name(tree, current_section, allocation_done, dot);
  582.       break;
  583.      default:
  584.       einfo("%F%S need more of these %d\n",tree->type.node_class );
  585.  
  586.     }
  587.   }
  588.  
  589.   return result;
  590. }
  591.  
  592.  
  593. static etree_value_type 
  594. exp_fold_tree_no_dot (tree, current_section, allocation_done)
  595.      etree_type *tree;
  596.      lang_output_section_statement_type *current_section;
  597.      lang_phase_type allocation_done;
  598. {
  599. return exp_fold_tree(tree, current_section, allocation_done, (bfd_vma)
  600.              0, (bfd_vma *)NULL);
  601. }
  602.  
  603. etree_type *
  604. exp_binop (code, lhs, rhs)
  605.      int code;
  606.      etree_type *lhs;
  607.      etree_type *rhs;
  608. {
  609.   etree_type value, *new;
  610.   etree_value_type r;
  611.  
  612.   value.type.node_code = code;
  613.   value.binary.lhs = lhs;
  614.   value.binary.rhs = rhs;
  615.   value.type.node_class = etree_binary;
  616.   r = exp_fold_tree_no_dot(&value,
  617.                abs_output_section,
  618.                lang_first_phase_enum );
  619.   if (r.valid)
  620.     {
  621.       return exp_intop(r.value);
  622.     }
  623.   new = (etree_type *)stat_alloc((bfd_size_type)(sizeof(new->binary)));
  624.   memcpy((char *)new, (char *)&value, sizeof(new->binary));
  625.   return new;
  626. }
  627.  
  628. etree_type *
  629. exp_trinop (code, cond, lhs, rhs)
  630.      int code;
  631.      etree_type *cond;
  632.      etree_type *lhs;
  633.      etree_type *rhs;
  634. {
  635.   etree_type value, *new;
  636.   etree_value_type r;
  637.   value.type.node_code = code;
  638.   value.trinary.lhs = lhs;
  639.   value.trinary.cond = cond;
  640.   value.trinary.rhs = rhs;
  641.   value.type.node_class = etree_trinary;
  642.   r= exp_fold_tree_no_dot(&value,  (lang_output_section_statement_type
  643.                     *)NULL,lang_first_phase_enum);
  644.   if (r.valid) {
  645.     return exp_intop(r.value);
  646.   }
  647.   new = (etree_type *)stat_alloc((bfd_size_type)(sizeof(new->trinary)));
  648.   memcpy((char *)new,(char *) &value, sizeof(new->trinary));
  649.   return new;
  650. }
  651.  
  652.  
  653. etree_type *
  654. exp_unop (code, child)
  655.      int code;
  656.      etree_type *child;
  657. {
  658.   etree_type value, *new;
  659.  
  660.   etree_value_type r;
  661.   value.unary.type.node_code = code;
  662.   value.unary.child = child;
  663.   value.unary.type.node_class = etree_unary;
  664.   r = exp_fold_tree_no_dot(&value,abs_output_section,
  665.                lang_first_phase_enum);
  666.   if (r.valid) {
  667.     return exp_intop(r.value);
  668.   }
  669.   new = (etree_type *)stat_alloc((bfd_size_type)(sizeof(new->unary)));
  670.   memcpy((char *)new, (char *)&value, sizeof(new->unary));
  671.   return new;
  672. }
  673.  
  674.  
  675. etree_type *
  676. exp_nameop (code, name)
  677.      int code;
  678.      CONST char *name;
  679. {
  680.   etree_type value, *new;
  681.   etree_value_type r;
  682.   value.name.type.node_code = code;
  683.   value.name.name = name;
  684.   value.name.type.node_class = etree_name;
  685.  
  686.  
  687.   r = exp_fold_tree_no_dot(&value,
  688.                (lang_output_section_statement_type *)NULL,
  689.                lang_first_phase_enum);
  690.   if (r.valid) {
  691.     return exp_intop(r.value);
  692.   }
  693.   new = (etree_type *)stat_alloc((bfd_size_type)(sizeof(new->name)));
  694.   memcpy((char *)new, (char *)&value, sizeof(new->name));
  695.   return new;
  696.  
  697. }
  698.  
  699.  
  700.  
  701.  
  702. etree_type *
  703. exp_assop (code, dst, src)
  704.      int code;
  705.      CONST char *dst;
  706.      etree_type *src;
  707. {
  708.   etree_type value, *new;
  709.  
  710.   value.assign.type.node_code = code;
  711.  
  712.  
  713.   value.assign.src = src;
  714.   value.assign.dst = dst;
  715.   value.assign.type.node_class = etree_assign;
  716.  
  717. #if 0
  718.   if (exp_fold_tree_no_dot(&value, &result)) {
  719.     return exp_intop(result);
  720.   }
  721. #endif
  722.   new = (etree_type*)stat_alloc((bfd_size_type)(sizeof(new->assign)));
  723.   memcpy((char *)new, (char *)&value, sizeof(new->assign));
  724.   return new;
  725. }
  726.  
  727. /* Handle PROVIDE.  */
  728.  
  729. etree_type *
  730. exp_provide (dst, src)
  731.      const char *dst;
  732.      etree_type *src;
  733. {
  734.   etree_type *n;
  735.  
  736.   n = (etree_type *) stat_alloc (sizeof (n->assign));
  737.   n->assign.type.node_code = '=';
  738.   n->assign.type.node_class = etree_provide;
  739.   n->assign.src = src;
  740.   n->assign.dst = dst;
  741.   return n;
  742. }
  743.  
  744. void 
  745. exp_print_tree (tree)
  746.      etree_type *tree;
  747. {
  748.   switch (tree->type.node_class) {
  749.   case etree_value:
  750.     print_address(tree->value.value);
  751.     return;
  752.   case etree_rel:
  753.     if (tree->rel.section->owner != NULL)
  754.       fprintf (config.map_file, "%s:",
  755.            bfd_get_filename (tree->rel.section->owner));
  756.     fprintf (config.map_file, "%s+", tree->rel.section->name);
  757.     print_address (tree->rel.value);
  758.     return;
  759.   case etree_assign:
  760. #if 0
  761.     if (tree->assign.dst->sdefs != (asymbol *)NULL){
  762.       fprintf(config.map_file,"%s (%x) ",tree->assign.dst->name,
  763.           tree->assign.dst->sdefs->value);
  764.     }
  765.     else {
  766.       fprintf(config.map_file,"%s (UNDEFINED)",tree->assign.dst->name);
  767.     }
  768. #endif
  769.     fprintf(config.map_file,"%s ",tree->assign.dst);
  770.     exp_print_token(tree->type.node_code);
  771.     exp_print_tree(tree->assign.src);
  772.     break;
  773.   case etree_provide:
  774.     fprintf (config.map_file, "PROVIDE (%s, ", tree->assign.dst);
  775.     exp_print_tree (tree->assign.src);
  776.     fprintf (config.map_file, ")");
  777.     break;
  778.   case etree_binary:
  779.     fprintf(config.map_file,"(");
  780.     exp_print_tree(tree->binary.lhs);
  781.     exp_print_token(tree->type.node_code);
  782.     exp_print_tree(tree->binary.rhs);
  783.     fprintf(config.map_file,")");
  784.     break;
  785.   case etree_trinary:
  786.     exp_print_tree(tree->trinary.cond);
  787.     fprintf(config.map_file,"?");
  788.     exp_print_tree(tree->trinary.lhs);
  789.     fprintf(config.map_file,":");
  790.     exp_print_tree(tree->trinary.rhs);
  791.     break;
  792.   case etree_unary:
  793.     exp_print_token(tree->unary.type.node_code);
  794.     if (tree->unary.child) 
  795.     {
  796.       
  797.     fprintf(config.map_file,"(");
  798.     exp_print_tree(tree->unary.child);
  799.     fprintf(config.map_file,")");
  800.   }
  801.     
  802.     break;
  803.   case etree_undef:
  804.     fprintf(config.map_file,"????????");
  805.     break;
  806.   case etree_name:
  807.     if (tree->type.node_code == NAME) {
  808.       fprintf(config.map_file,"%s", tree->name.name);
  809.     }
  810.     else {
  811.       exp_print_token(tree->type.node_code);
  812.       if (tree->name.name)
  813.       fprintf(config.map_file,"(%s)", tree->name.name);
  814.     }
  815.     break;
  816.   default:
  817.     FAIL();
  818.     break;
  819.   }
  820. }
  821.  
  822.  
  823.  
  824.  
  825. bfd_vma
  826. exp_get_vma (tree, def, name, allocation_done)
  827.      etree_type *tree;
  828.       bfd_vma def;
  829.      char *name;
  830.      lang_phase_type allocation_done;
  831. {
  832.   etree_value_type r;
  833.  
  834.   if (tree != (etree_type *)NULL) {
  835.     r = exp_fold_tree_no_dot(tree,
  836.          abs_output_section,
  837.               allocation_done);
  838.     if (r.valid == false && name) {
  839.       einfo("%F%S nonconstant expression for %s\n",name);
  840.     }
  841.     return r.value;
  842.   }
  843.   else {
  844.     return def;
  845.   }
  846. }
  847.  
  848. int 
  849. exp_get_value_int (tree,def,name, allocation_done)
  850.      etree_type *tree;
  851.      int def;
  852.      char *name;
  853.      lang_phase_type allocation_done;
  854. {
  855.   return (int)exp_get_vma(tree,(bfd_vma)def,name, allocation_done);
  856. }
  857.  
  858.  
  859. int
  860. exp_get_abs_int (tree, def, name, allocation_done)
  861.      etree_type *tree;
  862.      int def;
  863.      char *name;
  864.      lang_phase_type allocation_done;
  865. {
  866.   etree_value_type res;
  867.   res = exp_fold_tree_no_dot (tree, abs_output_section, allocation_done);
  868.  
  869.   if (res.valid)
  870.     {
  871.       res.value += res.section->bfd_section->vma;
  872.     }
  873.   else {
  874.     einfo ("%F%S non constant expression for %s\n",name);
  875.   }
  876.   return res.value;
  877. }
  878.